


#include "intrins.h"
#include "string.h"
//#define uchar unsigned char
//#define uint unsigned int  ///2串法拉电容， 300F-1500F
//#define u32 unsigned long

 #include <STC8.H>		 //STC8H1K28-LQP32

//#include <stc15.h>	
#define ADC_POWER   0x80            //ADC电源控制位
#define ADC_SPEEDLL 0x00            //540个时钟
#define ADC_START   0x08            //ADC起始控制位
#define ADC_FLAG    0x10            //ADC完成标志
// sfr ADC_CONTR   =   0xBC;           //ADC控制寄存器
// sfr ADC_RES     =   0xBD;           //ADC高8位结果
//sfr ADC_LOW2    =   0xBE;           //ADC低2位结果
//sfr P1ASF       =   0x9D;           //P1口第2功能控制寄存器
////fangx计算起点到终点需要的速禿=0,?

////J:\变压器点焊机\电容点焊机\kaixinguo.c
////********替换开心果程序*********
//2	STC15W408AS TSSOP20 IRC内部时钟选12MHZ	
//3	P1数码位段8个I0口，数码管位4个I0口	12个IO	
//4	编码器开关KA KB KC	3个10	
//1个点焊触发I0口,1个输出IO	一个电源控制	3个IO	
	
//15
//16	P55=P5.5	电源控制	改为P25
//17	P54=P5.4	驱动输出	
//18	P31=P3.1	TX	
//19	P30-P3.0	点焊触发	RX/INT4	
//20

	// STC8H1K28-SOP32 ,33.177MHZ
		 //P2.0-P2.7-a bcdefgdp，共阴数码管，段驱动
//7	P03=P0.3	个位	
//8	P02=P0.2	十位	
//9	P01=P0.1	百位	
//10	P00=P0.0	千位	
//11	//EC11编码器	
//12	P34=P3.4	KD菜单键	长按储存	
//13	P35=P3.5	KB加按键	短按	
//14	P36-P3.6	KA减按键	短按
	typedef unsigned int u16;	//对数据类型进行定义声明	
	typedef unsigned char u8;	//对数据类型进行定义声明	
	typedef unsigned long u32;	//对数据类型进行定义声明	
	
 	sbit KD   =P3^2;	//KD菜单键	
                 	
  sbit KB         =P3^3;            //KB加键
  sbit KA         =P3^4;           //KA减键
		// CQ3 P35 P01
		//CQ2 P36 P02
		//CQ1 P37 P03
		//CQ4 P31 P00  //P26 
	sbit keydianhan =P1^6;	//点焊触发	
	sbit fengming   =P2^2;	//蜂鸣器
  sbit kaiji      =P2^1;	//开关机
	
 	sbit syaok      =P2^0;	//升压ok
 sbit syaen      =P2^5;	//升压使能
		sbit out        =P5^4;	//驱动脉冲输出
  
	bit dianhan= 0;	      //点焊使能输出标志位
	bit flag10ms = 0;	      //10ms中断标志,扫描按键使用	
	
	bit keylong = 0;	      //KD设置按键长按标志	
 	u16 vfg = 0;	    //电压0.5s更新一次
	u8 caidan=0;	           //菜单
//  u16 a = 0;	            //点焊时间1-500，单位0.1ms，默认100值,10ms	
//	u16 b= 0;		          //焊接延时检测0.5s-5s
//	u16 c = 0;	            //双脉冲间隔时间1ms-200ms。
//	u16 d= 0;		          //脉冲次数
  u8 a = 0;	            //第一个脉冲时间单位毫秒
	u8 b= 0;		            //脉冲间隔时间单位毫秒
	u8 c = 0;	            //第二个脉冲时间
	u8 d= 0;		            //焊接延时检测单位秒
	u16 js= 0;              //关机记时间
	u32 v= 0;		          //电压                        
  
  u16 fm= 0;		          //蜂鸣器定时
  u16 m = 0;	         //防止循环触发
	u16 f= 2000;	         //实时保存设置参数
		u16 vadj= 0;		          //校准电压     
//	/++++++	+*+**+*+********数码管真值表-共阳********************/	
//	u8 code LEDchar[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //显示0~9的段码//显示缓存，0x46=b,0x83=c 0x41=v	小数点=0x7F,-=0xBF		
	u8 Ledbuff[4]={0xFF,0xFF,0xFF,0xFF};	//显示缓存，A= 0X77 0x7c=b,0x39=c 	小数点=0x80,-=0x40			 
 u8 code LEDchar[10]={0x3f,0x06,0x5b,0x4f,
                0x66,0x6d,0x7d,0x07,
                0x7f,0x6f	 }; //显示0~9的段码	数码管真值表-共阴
			//  0x77,0x7c,	0x39,0x5e,0x79,0x71,0x40,0x80  } //显示A-F的段码
                
void day(u16 c)		//
	
{
	unsigned char data i, j;
while(--c)
		{
	_nop_();
	_nop_();
	i = 29;
	j = 66;
	do
	{
		while (--j);
	} 
	
	while (--i);
}
}  
 void Init_ADC(void)
{  
   
       P1M0 &= ~0x80; P1M1 |= 0x80;  //打开P1.7口的ADC功能  ,P17 高阻输入：
    P_SW2 |= 0x80;
    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;
    ADCCFG = 0x0f;                              //设置ADC时钟为系统时钟/2/16
    ADC_CONTR = 0x80;                           //使能ADC模块


}
unsigned int adc(u8 ch)
{
        	unsigned int result;
	ADC_RES = 0;	
	ADC_RESL= 0;					//清掉ADC转换结果寄存器
    ADC_CONTR |= 0x40|ch;                      //启动AD转换
        _nop_();
        _nop_();
        while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
        ADC_CONTR &= ~0x20;                     //清完成标志
    
                 //返回ADC结果
	  	result = ADC_RES<<4|ADC_RESL;	//读取12位转换结果保存到result
    return result;                    //返回ADC转换结果12位
}	 	
  
	/***************************关闭IAP***********+************/	
void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}
	/*************++********** IAP读*+***+**+*********+********/	
u8 IapRead(u16 addr)
{
    char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 33;                               //设置等待参数33MHz
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

//	/**+*+****+*+**+*****扇区擦除*+*4	**/	
void IapErase(u16 addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 33;                               //设置等待参数33MHz
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}
	//**********IAP写**	**********/	
void IapProgram(u16 addr, u8 dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 33;                               //设置等待参数33MHz
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

	/**************+******KC扫描*************************/	
	void kccan()	
 {
	  static u16 set = 0;	//KC菜单键扫描次数	
  
	  static u16 b1 = 0; 

	  
	if(flag10ms)	                                    //10ms时间标志,由Tim2中断10次计数产生	
	{flag10ms =0;	                                    //清零10ms标志	
//		vfg++;                                          //电压更新时间+1
	    js++;                                         //开关机计时＋1
		  if(f<2000)                                     //更改参数 20秒后自动保存参数
				{
				f++;
					if(f>1999)
						{
							fm=60;
						IapErase(0x0000);	                         //擦除第1扇区，STC8H1K28首扇区位置	
              IapProgram(0x0001,a);	                       //将a写入第1字节	
              IapProgram(0x0002,b);	
						IapProgram(0x0003,c);		
						IapProgram(0x0004,d);	
							IapProgram(0x0005,vadj);
					 	IapProgram(0x0006,vadj>>8);	  //
						}
				}
 		
     if(vfg>50)                                       //0.5更新一次显示电压
 			{
 			vfg=0;
 			v=adc(7);
 				v=v*vadj*3.3/100/1024;
 				if(v<380){dianhan=0;day(200);kaiji=0;while(1);}//电压低压3.8v先关闭脉冲再关机
 			}	 	
			
	if(js>36000){kaiji=0;fm=55;}//6分钟后关机	 ,蜂鸣响提醒，。
	////////////////////////////////////////////////////////
			if(KD)	//KD菜单按键按下过程中抖动，或弹起后	
				{

					
					if(set > 2)	//按键按下大于10ms	
					 {fm=30; 
						caidan++;	//菜单	
							if(caidan>4)	
							{	
							caidan=0;	
							}	
							set= 0;	
						}
					
					
				set= 0;	//按键时间清零，清零后重新计数	
					
					
				}	
				else	//KD按键按下	
				{
				set++;		
					if(set>65534){set = 211;}	//以下防止set扫描次数溢出	
					if(set>=200)
					{fm=300;} //KC按键时间大于2S	关机kaiji=0;while(1);		
				}					
		////////////////////////////////////////////////////////	dianhan=0;				
				if(keydianhan)
				{
					b1=0;
				 	if(m>1000){syaen=0;}
				}
				else
				{   syaen=1;
				 	if(syaok==0)
           {
            b1++;
						if(m<100 ){m=0;}//防止点焊完成后循环触发
							if(b1>=d&&m>1000)
							{
								
								fm=30;	dianhan=1;b1=0;
							

							}
           }
         
					
				}

				
						
					
					 
				 
	 }		

 }
//	/++++++++++++++++++++++++参数设置+++++++++++++++++++++++**++/	
	void casnhu()	//EC11旋转编码器一定位一脉冲驱动编程	
{
	static char LastA=0;	//EC11旋转编码器的A引脚上一次的状态	
	static char LastB= 0;	//EC11旋转编码器的B引脚上一次的状态	
            
	if(KA != LastA)	//判断EC11旋转编码器A引脚是否等于上一次的状态	
	{	
	if(KA == 0)	//EC11旋转编码器旋转后，判断KA是否是低电平状态	
  {
			if(KB == 0)	//判断KB引脚当前状态,高电平则为正转	
			{fm=5;f=0;
				if(caidan ==0) {a--;if(a<1){a = 200;}}	      //第一个脉冲时间单位毫秒
				if(caidan ==1) {b--;if(b<1){b = 250;}}	        //脉冲间隔时间单位毫秒
				if(caidan ==2) {c--;if(c<1){c = 200;}}	      //第二个脉冲时间
				if(caidan ==3) {d-=2; if(d< 1){d = 255;} }	  //焊接延时检测单位秒
					if(caidan ==4) {vadj-=1; if(d< 1){d = 999;} }	  //VADJ 分压比调整
			}                                                               
			else	
			{	
			if(caidan ==0) 
			{a++;
			if(a>200)
			{a = 1;}
			}	
			if(caidan ==1) 
			{b++;
			if(b>255)
			{b = 1;}
			}	
			if(caidan ==2) {c++;if(c>200){c =1;}}	
			if(caidan ==3) {d+=2; if(d>255){d = 1;} }
			if(caidan ==4) {vadj+=1; if(d> 998){d = 1;}}
		 fm=5;f=0;
			}	
			
			
	}	
	LastA = KA;	//更新编码器上一个状态暂存变量	
	LastB = KB;	//更新编码器上一个状态暂存变量	
	}	


}
	/****.*******.************LED缓存函数***********.****.*雷*************/	
	void LED()			//  0x77,0x7c,	0x39,0x5e,0x79,0x71,0x40,0x80  } //显示A-F的段码
{
	if(keydianhan ==0)
      {	   ;
	  Ledbuff[0] = LEDchar[v%10];               //个位 
       Ledbuff[1] = LEDchar[v/10%10];            //十位
       Ledbuff[2] = LEDchar[v/100]&0x7F;         //百位+小数点
		   Ledbuff[3] = 0x2f	;                        //V
	     } 
			else{
	if(caidan ==0)	
			{	 
			Ledbuff[3]	= LEDchar[a%10];	             //个位	
			Ledbuff[2]	=	LEDchar[a/10%10];	     //十位	+小数点	 	Ledbuff[2]	=	LEDchar[a/10%10]&0x80;	 
			Ledbuff[1]  =0x40;//LEDchar [a/100];	           //百位-	
			Ledbuff [0] = 0x77;	                       //千位A	
				  
		 }
		if(caidan ==1)
      {			 	
       Ledbuff[3] = LEDchar[b%10];               //个位 
       Ledbuff[2] = LEDchar[b/10%10]; ;            //十位
       Ledbuff[1] = LEDchar[b/100];         //百位+小数点Ledbuff[1] = LEDchar[b/100]&0x80;
		   Ledbuff[0] = 0x7c;	                        //千位b	
		   	 
	     } 
    if(caidan ==2)
      {	   	  
       Ledbuff[3] = LEDchar[c%10];               //个位 
       Ledbuff[2] = LEDchar[c/10%10]; ;            //十位
       Ledbuff[1] =  0x40;//LEDchar[c/100];               //百位   -
		   Ledbuff[0] = 0x39;	//C                        //千位C
		   	 	
	     } 
    if(caidan ==3)
      {	  	 
       Ledbuff[3] = LEDchar[d%10];               //个位 
       Ledbuff[2] = LEDchar[d/10%10];            //十位
       Ledbuff[1] = LEDchar[d/100]|0x80;         //百位+小数点
		   Ledbuff[0] = 0x5e;	   //d		 /千位d	
		  	 
                                           				
	     } 		
		 	if(caidan ==4)
       {
       Ledbuff[0] = LEDchar[vadj%10];               //个位 
        Ledbuff[1] = LEDchar[vadj/10%10];            //十位
       Ledbuff[2] = LEDchar[vadj/100]&0x7F;         //百位+小数点
 		   Ledbuff[3] = 0x2f;	                        //E
 	     } 	
		 }
}

void Timer0_Init(void)		//2微秒@33.1776MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0xBE;				//设置定时初始值
	TH0 = 0xFF;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
}
   void Timer2_Init(void)		//1毫秒@33.1776MHz
{
	AUXR |= 0x04;			//定时器时钟1T模式
	T2L = 0x66;				//设置定时初始值
	T2H = 0x7E;				//设置定时初始值
	AUXR |= 0x10;			//定时器2开始计时
	IE2 |= 0x04;			//使能定时器2中断
}
 




//	**********主函数*******	
	
void main()	
	{	 
	    P1M0 |= 0x7f; P1M1 &= ~0x7f; //P1-P16推挽
 
		 
      P3M0 = (P3M0 & ~0x1e) | 0xe0; P3M1 &= ~0xfe; //P31 -4 设置为准双向口  5,6,7推挽输出

 
	   
		     P0M0 = 0xff; P0M1 = 0x00; //  P0 推挽输出		推挽输出     段位选择 共阴。 
		        P1M0 = 0x80; P1M1 = 0x00; 	//P1准双向口， P17 为脉冲输出，
	
			     
	  
             P3PU = 0x0c; 	 //p33 P32 打开内部上拉电阻。

            P2M0 = 0x4c; P2M1 = 0x00;  //P2.2 2.3 2.6设置为推挽口， 其余准双向口
	
		    P5M0 |= 0x10; P5M1 &= ~0x10;  //  P54  推挽输出
	
  

  
	PT0= 1;           	          //设置Tim0中断为高级		

  syaen=0;                    //关闭升压

  out = 0; 	                    //关闭点焊输出脉冲
  EA= 1;	                      //开启总中断	
 	ES=1;
kaiji=0;
Init_ADC( )	;
			P35=1;P36=0;P37=0 ;P2=0x40;	 //0x40 -			 个 位，十位，百位，千位
		day(190);
//			kaiji=1;    //开机
	   	P35=0;P36=1;P37=0 ;P2=0x40;	 //0x40 -			 个 位，十位，百位，千位
	   	 day(190);
	   	P35=0;P36=0;P37=1 ;P2=0x40;	 //0x40 -			 个 位，十位，百位，千位
		 	day(190);
	//	 	P03=0;P02=0;P01=0;P00=1;P2=0x40;	 //0x40 -			 个 位，十位，百位，千位
		  day(190);
	
	 a = (u8)IapRead(0x0001);	      //读取第1字节数值赋给a	
 
	 b = (u8)IapRead(0x0002);	    //读取第1字节数值赋给d	
   
   c = (u8)IapRead(0x0003);
	 
	 d = (u8)IapRead(0x0004);
		vadj=(u8)IapRead(0x0005)+ (u8)IapRead(0x0006)*100 ; // vadj 999- 1
		if(vadj==0||vadj>999)
    vadj=600;	
    Timer0_Init()	;

	  Timer2_Init();
	 	 

		//	day(100);
		fm=70; 
	
		while(KD==0);	
  
	while(1)	                      //主循环	
	{


		
	if(keydianhan==0){dianhan=1;}else dianhan=0;
		
		
		
	kccan();	                   //调入按键扫描函数	
	casnhu();	                   //调入参数设置函数	

	
	LED();	                       //调入数码管缓存函数	
	}
}					   
 

	/**********定时器Tim0中断执行函数关闭点焊输出级别最高************/	
	void Timer0_Isr(void) interrupt 1	  //2微秒@33.1776MHz
	{
			static u8 i= 0;	               //设置静态变量i,显示使用	
	static u16 j = 0;	

		static 	u8 tmp;			 // 保存显示状态	  

	if(dianhan== 1&&syaok==0)
 
	{
	m=0;	    //防止循环触发
	  
	
	 j++; 

	switch(i)	
	{//	P0=0; // 关闭显示 ，再点焊 j>=a*50 j
		
	case 0: out=0; tmp=P0;P0=0; out=1;i=1;break;  // 关闭显示 ，再点焊 //  
	case 1:  if(j>=a*50){out=0;j=0;i=2;}; break;    //首个间隔开始，	a*50 X2US=a*0.1 MS
	case 2:  if(j>=b*50){  out=1;j=0;i=3;} break; 	//开始输出脉冲	,
  case 3:  if(j>=c*50){out=0;j=0;dianhan= 0;P0=tmp;} break; 	  // 结束后， P0恢复显示。	
	default: break;	
	}	
	
	
	}
	
else//点焊输出关闭数码管显示减少电压对单片机的干扰
{
	 out=0;i=0; 	 //关闭 驱动脉冲。

} 		
                  
	
	

	
}
		
		
		


	/**********定时器Tim2中断 执行函数数码管显示级别低************/	
void Timer2_Isr(void) interrupt 12
	{	static u8 j=0;	                  //设置静态变量i:10ms标志用	
		static u8 i= 0;	               //设置静态变量i,显示使用	
		T2L = 0x66;				//设置定时初始值
	T2H = 0x7E;				//设置定时初始值
		
		if(m<1500){m++;}

if(fm > 0)
{fm--;fengming =0;js=0;}
else{fengming = 1;}
	
		j++;	
	if(j>9)	{	j=0;flag10ms=1;}//产生10ms标志位,用于按键扫描		
		
//	if()
//{

//}
	P0= 0x00;	//4个段 选 //也可能要取反， P2=!P2
  
   P23=0;	//数码管消隐 	
		switch(i)	  //p23 小数点
	{	
	case 0: P0=0xfe;P31=P00;P26=P00;i++;P1=Ledbuff[0]; break; //关闭 个位显示， 然后给个位Ledbuff[0] 赋值	P1
	case 1: P0=0xfd; P35=P01;;i++;P1=Ledbuff[1];P27=0; if(caidan ==1||caidan ==2||caidan ==3); P23=1;   break; //+关闭 十位显示， 然后给十位Ledbuff[1] 赋值	 P1
	case 2:P0=0xfb;P36=P02;i++;
	if(caidan ==3)
	{P23=1;P1=Ledbuff[2];}
	else P23=0;P1=Ledbuff[2]; break; //关闭 百位显示， 然后给  百位Ledbuff[2] 赋值	 P21
	case 3: P0=0xf7;;P37=P03;i=0;P1=Ledbuff[3]; break; ///关闭 千位显示， 然后给  千位Ledbuff[3] 赋值	 P2P27=1	
	default: break;	
	}	

		
	}